perm filename STREAM.MSS[WHT,LSP] blob sn#754072 filedate 1984-05-12 generic text, type T, neo UTF8
@Part[Stream, Root = "CLM.MSS"]
@Comment{Chapter of Common Lisp Manual.  Copyright 1984 Guy L. Steele Jr.⎇


@MyChapter[Streams]
@label[STREAM]

Streams are objects that serve as sources or sinks of data.
Character streams produce or absorb characters;
binary streams produce or absorb integers.
The normal action of a @clisp system is to read characters from
a character input stream, parse the characters as representations
of @clisp data objects, evaluate each object (as a form) as it is read, and
print representations of the results of
evaluation to an output character stream.

Typically streams are connected to files or to an interactive terminal.
Streams, being @xlisp objects, serve as the ambassadors of external
devices by which input/output is accomplished.

A stream, whether a character stream or a binary
stream, may be input-only, output-only, or bidirectional.
What operations may be performed on a stream depends on which of
the six types of stream it is.

@Section [Standard Streams]

There are several variables whose values are streams used by many
functions in the @xLisp system.  These variables and their uses are
listed here.  By convention, variables that are expected to hold a
stream capable of input have names ending with @f[-input], and
similarly @f[-output] for output streams.  Those expected to hold a
bidirectional stream have names ending with @f[-io].

@Defvar[Var {standard-input⎇]
In the normal @xlisp top-level loop, input is read from
@Var[standard-input] (that is, whatever stream is the value of the global
variable @Var[standard-input]).  Many input functions, including
@Funref[read] and @Funref[read-char], take a stream argument that defaults to
@Var[standard-input].
@Enddefvar

@Defvar[Var {standard-output⎇]
In the normal @xLisp top-level loop, output is sent to
@Var[standard-output] (that is, whatever stream is the value of the global
variable @Var[standard-output]).  Many output functions, including
@Funref[print] and @Funref[write-char], take a stream argument that defaults
to @Var[standard-output].
@Enddefvar

@Defvar[Var {error-output⎇]
The value of @var[error-output] is a stream to which error messages
should be sent.  Normally this is the same as @var[standard-output],
but @var[standard-output] might be bound to a file and @var[error-output]
left going to the terminal or a separate file of error messages.
@Enddefvar

@Defvar[Var {query-io⎇]
The value of @var[query-io] is a stream to be used when
asking questions of the user.  The question should be output to this
stream, and the answer read from it.  When
the normal input to a program may be coming from a file, questions such
as ``Do you really want to delete all of the files in your directory?'' should
nevertheless
be sent directly to the user; and the answer should come from the user,
not from the data file.  For such purposes @var[query-io] should be
used instead of @var[standard-input] and @var[standard-output].
@var[query-io] is used by such functions
as @Funref[yes-or-no-p].
@Enddefvar

@Defvar[Var {debug-io⎇]
The value of @var[debug-io] is a stream to be used for interactive
debugging purposes.  This is often the same as the value of @Varref[query-io],
but need not be.
@Enddefvar

@Defvar[Var {terminal-io⎇]
The value of @var[terminal-io] is ordinarily
the stream that connects to the user's console.
Typically, writing to this stream would cause the output to appear
on a display screen, for example, and reading from the stream would
accept input from a keyboard.  It is intended
that standard input functions such as @Funref[read] and @Funref[read-char],
when used with this stream, would cause ``echoing'' of the input
into the output side of the stream.  (The means by which this is
accomplished are of course highly implementation-dependent.)
@Enddefvar

@Defvar[Var {trace-output⎇]
The value of @var[trace-output] is the stream on which the @Macref[trace]
function prints its output.
@Enddefvar

@var[standard-input], @var[standard-output], @var[error-output],
@var[trace-output], @var[query-io], and @var[debug-io]
are initially bound to synonym streams that pass all
operations on to the stream that is the value of @var[terminal-io].
(See @Funref[make-synonym-stream].)
Thus any operations performed on those streams will go to the terminal.

No user program should ever change the value of @var[terminal-io].  A program
that wants (for example) to divert output to a file should do so by binding
the value of @var[standard-output]; that way error messages sent to
@var[error-output] can still get to the user by going through @var[terminal-io],
which is usually what is desired.

@Section [Creating New Streams]

Perhaps the most important constructs for creating new streams
are those that open files; see @Macref[with-open-file] and @Funref[open].
The following functions construct streams without reference to a file system.

@Defun[Fun {make-synonym-stream⎇, Args {@i[symbol]⎇]
@f[make-synonym-stream] creates and returns
a ``synonym stream.''
Any operations on the new stream will be performed on the stream
that is then the value of the dynamic variable named by the @i[symbol].
If the value of the variable should change or be bound,
then the synonym stream will operate on the new stream.
@Enddefun

@Defun[Fun {make-broadcast-stream⎇, Args {@rest @i[streams]⎇]
This returns a stream that only works in the output direction.  Any output
sent to this stream will be sent to all of the @i[streams] given.
The set of
operations that may be performed on the new stream is the intersection
of those for the given streams.  The results returned by a stream
operation are the values resulting from
performing the operation on the last stream in @i[streams]; the
results of performing the operation on all preceding streams are
discarded.
If no @i[streams] are given as arguments, then the result
is a ``bit sink''; all output to the resulting stream is discarded.
@Enddefun

@Defun[Fun {make-concatenated-stream⎇, Args {@rest @i[streams]⎇]
This returns a stream that only works in the input direction.
Input is taken from the first of the @i[streams] until it reaches
end-of-file; then that stream is discarded, and input is taken
from the next of the @i[streams], and so on.  If no arguments
are given, the result is a stream with no content; any input attempt
will result in end-of-file.
@Enddefun

@Defun[Fun {make-two-way-stream⎇, Args {@i[input-stream] @i[output-stream]⎇]
This returns a bidirectional stream that gets its input from @i[input-stream]
and sends its output to @i[output-stream].
@Enddefun

@Defun[Fun {make-echo-stream⎇, Args {@i[input-stream] @i[output-stream]⎇]
This returns a bidirectional stream that gets its input from @i[input-stream]
and sends its output to @i[output-stream].  In addition, all
input taken from @i[input-stream] is echoed to @i[output-stream].
@Enddefun

@Defun[Fun {make-string-input-stream⎇, Args {@i[string] @optional @i[start] @i[end]⎇]
This returns an input stream.
The input stream will supply, in order, the characters in the substring
of @i[string] delimited by @i[start] and @i[end]; after the last
character has been supplied, the stream will then be at end-of-file.
@Enddefun

@Defun[Fun {make-string-output-stream⎇, Args {⎇]
This returns an output stream that will 
accumulate all output given it for the benefit of the function
@f[get-output-stream-string].
@Enddefun

@Defun[Fun {get-output-stream-string⎇, Args {@i[string-output-stream]⎇]
Given a stream produced by @f[make-string-output-stream], this
returns a string containing all the characters output to the stream so far.
The stream is then reset; thus each call to @f[get-output-stream-string]
gets only the characters since the last such call (or the creation
of the stream, if no such previous call has been made).
@Enddefun

@Defmac[Fun {with-open-stream⎇, Args {(@i[var] @i[stream]) @mstar<@i[declaration]> @Mstar<@i[form]>⎇]
The form @i[stream] is evaluated and must produce a stream.
The variable @i[var] is bound with the stream as its value,
and then the forms of the body are executed
as an implicit @f[progn]; the results of evaluating
the last form are returned as the value of the @f[with-open-stream] form.
The stream
is automatically closed on exit from the @f[with-open-stream] form,
no matter whether the exit is normal or abnormal;
see @Funref[close].
The stream should be regarded as having dynamic extent.
@enddefmac

@Defmac[Fun {with-input-from-string⎇, Args {(@i[var] @i[string] @mstar<@i[keyword] @i[value]>) @mstar<@i[declaration]> @Mstar<@i[form]>⎇]
The body is executed as an implicit @f[progn] with the variable @i[var]
bound to a character input stream that supplies successive characters from
the value of the form @i[string].  @f[with-input-from-string]
returns the results from the last @i[form] of the body.

The input stream is automatically closed on exit from
the @f[with-input-from-string] form,
no matter whether the exit is normal or abnormal.
The stream should be regarded as having dynamic extent.

The following keyword options may be used:
@keywordlist[with-input-from-string]
@keyword[index]
The form after the @Kwd[index] keyword should be a @i[place]
acceptable to @f[setf].  If the @f[with-input-from-string] form
is exited normally, then the @i[place] will have stored into it the
index into the @i[string] indicating the first character not read
(the length of the string if all characters were used).
The @i[place] is not updated as reading progresses, but only at the
end of the operation. 
@endkeyword

@keyword[start]
The @Kwd[start] keyword takes an argument indicating, in the manner
usual for sequence functions, the beginning of
a substring of @i[string] to be used.
@endkeyword

@keyword[end]
The @Kwd[end] keyword takes an argument indicating, in the manner
usual for sequence functions, the end of
a substring of @i[string] to be used.
@endkeyword
@endkeywordlist

Here is an example of the use of @f[with-input-from-string]:
@lisp
(with-input-from-string (s "Animal Crackers" :index j :start 6)
  (read s)) @EV crackers
@endlisp
As a side effect, the variable @f[j] is set to @f[15].

The @Kwd[start] and @Kwd[index] keywords may both specify
the same variable, which is a pointer within the string to be advanced,
perhaps repeatedly by some containing loop.
@Enddefmac

@Defmac[Fun {with-output-to-string⎇, Args {(@i[var] @mopt<@i[string]>) @mstar<@i[declaration]> @Mstar<@i[form]>⎇]
The body is executed as an implicit @f[progn] with the variable @i[var]
bound to a character output stream.  All output to that stream
is saved in a string.  This may be done in one of two ways.

If no @i[string] argument is provided, then
the value of
@f[with-output-from-string] is a string containing all the collected output.

If @i[string] is specified, it must be a string with a fill pointer;
the output is incrementally appended to the string,
as if using @Funref[vector-push-extend] if the string is adjustable,
and otherwise as if using @f[vector-push].
In this case @f[with-output-to-string]
returns the results from the last @i[form] of the body.

In either case,
the output stream is automatically closed on exit from
the @f[with-output-from-string] form,
no matter whether the exit is normal or abnormal.
The stream should be regarded as having dynamic extent.
@Enddefmac


@Section [Operations on Streams]

This section contains discussion of only those operations that
are common to all streams.  Input and output is rather complicated
and is discussed separately in chapter @ref[IO].
The interface between streams and the file system is discussed
in chapter @ref[FILES].

@Defun[Fun {streamp⎇, Args {@i[object]⎇]
@f[streamp] is true if its argument is a stream,
and otherwise is false.
@Lisp
(streamp x) @EQ (typep x 'stream)
@Endlisp
@Enddefun

@Defun[Fun {input-stream-p⎇, Args {@i[stream]⎇]
This predicate is true if its argument (which must be a stream) can handle
input operations, and otherwise is false.
@Enddefun

@Defun[Fun {output-stream-p⎇, Args {@i[stream]⎇]
This predicate is true if its argument (which must be a stream) can handle
output operations, and otherwise is false.
@Enddefun

@Defun[Fun {stream-element-type⎇, Args {@i[stream]⎇]
A type specifier is returned to indicate what objects
may be read from or written to the argument @i[stream], which must be a stream.
Streams created by @Funref[open] will have an element type
restricted to a subset of @f[character] or @f[integer],
but in principle a stream may conduct transactions using any
@xlisp objects.
@Enddefun

@Defun[Fun {close⎇, Args {@i[stream]⎇, Keys {[abort]⎇]
The argument must be a stream.
The stream is closed.  No further input/output operations may be performed
on it.  However, certain inquiry operations may still be performed,
and it is permissible to close an already closed stream.

If the @Kwd[abort] parameter is not @false (it defaults to @false), it
indicates an abnormal termination of the use of the stream.  An attempt
is made to clean up any side effects of having created the stream in the
first place.  For example, if the stream performs output to a file
that was newly created when the stream was created, then if possible the
file is deleted and any previously existing file is not superseded.
@Enddefun